#include "gtest/gtest.h"
#include "DataStructure/Common/Constant.h"
#include "../../IntegrationFormula/Gauss3DTetra4.h"
#include "../Tetra4NodeShpFunc.h"

using SG::Algebra::Matrixd;
using SG::DataStructure::Common::TOLERANCE;
using SG::FEMSolver::Element::Tetra4NodeShpFunc;

// 形函数在本点为 1，他点为 0
TEST (Tetra4NodeShpFuncTest, shpFuncTest)
{
    // Input
    SG::DataStructure::FEM::IntegPointArray integs (4);
    integs[0].m_x =  0.0; integs[0].m_y =  0.0; integs[0].m_z =  0.0;
    integs[1].m_x =  1.0; integs[1].m_y =  0.0; integs[1].m_z =  0.0;
    integs[2].m_x =  0.0; integs[2].m_y =  1.0; integs[2].m_z =  0.0;
    integs[3].m_x =  0.0; integs[3].m_y =  0.0; integs[3].m_z =  1.0;

    // Test data
    auto shpfunc = Tetra4NodeShpFunc ();
    shpfunc.Compute (integs);

    // 测试 1 号节点处形函数
    auto& m1Test = shpfunc.GetShapeFunction (0);
    auto m1Target = Matrixd (4, 1); m1Target (0, 0) = 1.0;
    ASSERT_TRUE (m1Test == m1Target);

    // 测试 2 号节点处形函数
    auto& m2Test = shpfunc.GetShapeFunction (1);
    auto m2Target = Matrixd (4, 1); m2Target (1, 0) = 1.0;
    ASSERT_TRUE (m2Test == m2Target);

    // 测试 3 号节点处形函数
    auto& m3Test = shpfunc.GetShapeFunction (2);
    auto m3Target = Matrixd (4, 1); m3Target (2, 0) = 1.0;
    ASSERT_TRUE (m3Test == m3Target);

    // 测试 4 号节点处形函数
    auto& m4Test = shpfunc.GetShapeFunction (3);
    auto m4Target = Matrixd (4, 1); m4Target (3, 0) = 1.0;
    ASSERT_TRUE (m4Test == m4Target);
}

// 标准母元，Jacobian 矩阵为单位矩阵
TEST (Tetra4NodeShpFuncTest, shpFuncDerivativeTest)
{
    // Input
    SG::FEMSolver::Element::Gauss3DTetra4 integCalc;
    auto integs = integCalc.GetPoints ();
    Matrixd nodes (4, 3);
    nodes (0, 0) =  0.0; nodes (0, 1) =  0.0; nodes (0, 2) =  0.0;
    nodes (1, 0) =  1.0; nodes (1, 1) =  0.0; nodes (1, 2) =  0.0;
    nodes (2, 0) =  0.0; nodes (2, 1) =  1.0; nodes (2, 2) =  0.0;
    nodes (3, 0) =  0.0; nodes (3, 1) =  0.0; nodes (3, 2) =  1.0;

    // Target data
    auto I = SG::Algebra::identity (3);

    // Test data
    auto shpfunc = Tetra4NodeShpFunc ();
    shpfunc.Compute (integs);

    // 测试 4 个积分点形函数导数
    for (std::size_t index{0}; index < 4; ++index)
    {
        auto I1 = shpfunc.GetShapeFunctionDerivative (index) * nodes;
        ASSERT_TRUE (I1 == I);
    }
}